//
// Created by shen on 2025/3/20.
//

#ifndef VIDEOEDIT_JAVACALLHELPER_H
#define VIDEOEDIT_JAVACALLHELPER_H
#include <jni.h>
#include <LogUtil.h>
#define THREAD_MAIN  1
#define THREAD_CHILD  2
class JavaCallHelper {
public:
    JavaCallHelper(JavaVM *_javaVM,JNIEnv *_env,jobject &_jobj):javaVm(_javaVM){
        env=_env;
        jobj = _env->NewGlobalRef(_jobj);
        jclass jffPlayer = _env->GetObjectClass(jobj);
        jmid_onstatus = _env->GetMethodID(jffPlayer,"onStatus","(I)V");
        jmid_onframe =_env->GetMethodID(jffPlayer,"onFrameYUV","(II[B[B[BID)V");
        jmid_onCallYUVToBitmap=_env->GetMethodID(jffPlayer,"onCallYUVToBitmap","(II[B[B[BID)V");
        jmid_onchanged=_env->GetMethodID(jffPlayer,"onSizeChange","(II)V");
        jmid_onGetFrameInitSuccess= env->GetMethodID(jffPlayer,"onGetFrameInitSuccess","(Ljava/lang/String;II[B[B)V");;
    }
    virtual ~JavaCallHelper() {
        env->DeleteGlobalRef(jobj);
        jobj = 0;
    }
public:


    void onLoad(bool isLoad, int thread){
        if (thread == THREAD_CHILD){
            JNIEnv *jniEnv;
//            if (javaVm->AttachCurrentThread(&jniEnv,0) != JNI_OK){
//                return;
//            }
//            jniEnv->CallVoidMethod(jobj,jmid_load,isLoad);
//            javaVm->DetachCurrentThread();
        } else{
//            env->CallVoidMethod(jobj,jmid_load,isLoad);
        }
    }

    void onFrameYUVTobitmap(int thread,int width, int height, uint8_t *fy, uint8_t *fu, uint8_t *fv,
                    int practicalWidth,double pts){

        if (thread == THREAD_CHILD) {
            JNIEnv *jniEnv;
            if (javaVm->AttachCurrentThread(&jniEnv, nullptr) != JNI_OK) {
                return;
            }


            jbyteArray y = jniEnv->NewByteArray(width * height);
            jniEnv->SetByteArrayRegion(y, 0, width * height, reinterpret_cast<const jbyte *>(fy));
            jniEnv->DeleteLocalRef(y);

            jbyteArray u = jniEnv->NewByteArray(width * height / 4);
            jniEnv->SetByteArrayRegion(u, 0, width * height / 4, reinterpret_cast<const jbyte *>(fu));
            jniEnv->DeleteLocalRef(u);

            jbyteArray v = jniEnv->NewByteArray(width * height / 4);
            jniEnv->SetByteArrayRegion(v, 0, width * height / 4, reinterpret_cast<const jbyte *>(fv));
            jniEnv->DeleteLocalRef(v);
            jniEnv->CallVoidMethod(jobj, jmid_onCallYUVToBitmap, width, height, y, u, v, practicalWidth,
                                   pts);





            javaVm->DetachCurrentThread();
        } else {
            jbyteArray y = env->NewByteArray(width * height);
            env->SetByteArrayRegion(y, 0, width * height, reinterpret_cast<const jbyte *>(fy));

            jbyteArray u = env->NewByteArray(width * height / 4);
            env->SetByteArrayRegion(u, 0, width * height / 4, reinterpret_cast<const jbyte *>(fu));

            jbyteArray v = env->NewByteArray(width * height / 4);
            env->SetByteArrayRegion(v, 0, width * height / 4, reinterpret_cast<const jbyte *>(fv));
            env->CallVoidMethod(jobj, jmid_onCallYUVToBitmap, width, height, y, u, v, practicalWidth,
                                pts);

            env->DeleteLocalRef(y);
            env->DeleteLocalRef(u);
            env->DeleteLocalRef(v);
        }

    }

    void onChangeSize(int thread,int width,int height){
        if (thread == THREAD_CHILD){
            JNIEnv *jniEnv;
            if(javaVm->AttachCurrentThread(&jniEnv,0) != JNI_OK){
                return;
            }
            jniEnv->CallVoidMethod(jobj,jmid_onchanged,width,height);
            javaVm->DetachCurrentThread();
        }else{
            env->CallVoidMethod(jobj,jmid_onstatus);
        }
    }
    void onStatus(int thread,int status){
        if (thread == THREAD_CHILD){
            JNIEnv *jniEnv;
            if(javaVm->AttachCurrentThread(&jniEnv,0) != JNI_OK){
                return;
            }
            jniEnv->CallVoidMethod(jobj,jmid_onstatus,status);
            javaVm->DetachCurrentThread();
        }else{
            env->CallVoidMethod(jobj,jmid_onstatus);
        }
    }


    void onGetFrameInitSuccess(const char *codecName,int width,int height, int csd0_size, int csd1_size,uint8_t *csd_0,uint8_t *csd_1){
        JNIEnv *jniEnv;
        if(javaVm->AttachCurrentThread(&jniEnv,0) != JNI_OK){
            return;
        }
        jstring name = jniEnv->NewStringUTF(reinterpret_cast<const char *>(codecName));
        jbyteArray csd0 = jniEnv->NewByteArray(csd0_size);
        jniEnv->SetByteArrayRegion(csd0, 0, csd0_size, reinterpret_cast<const jbyte *>(csd_0));
        jbyteArray csd1 = jniEnv->NewByteArray(csd1_size);
        jniEnv->SetByteArrayRegion(csd1, 0, csd1_size, reinterpret_cast<const jbyte *>(csd_1));

        jniEnv->CallVoidMethod(jobj,jmid_onGetFrameInitSuccess,name,width,height,csd0,csd1);
        jniEnv->DeleteLocalRef(name);
        jniEnv->DeleteLocalRef(csd0);
        jniEnv->DeleteLocalRef(csd1);
        javaVm->DetachCurrentThread();
    }

private:
    JavaVM *javaVm;
    JNIEnv *env;
    jobject jobj;
    jmethodID jmid_onframe;
    jmethodID jmid_onstatus;
    jmethodID jmid_onchanged;
    jmethodID jmid_onCallYUVToBitmap;
    jmethodID jmid_onGetFrameInitSuccess;
};


#endif //VIDEOEDIT_JAVACALLHELPER_H
